package br.com.simtecnologia.access.controll.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import br.com.caelum.vraptor.ioc.SessionScoped;
import br.com.caelum.vraptor.ioc.Stereotype;
import br.com.simtecnologia.access.controll.DefaultLoginSession;
import br.com.simtecnologia.access.controll.LoginSession;
import br.com.simtecnologia.access.controll.handlers.AccessControlNameResolved;

/**
 * Define uma anotação para identificar um Recurso com Controle de Acesso, para
 * suas lógicas, podendo definir as propriedades necessárias para tal.
 * @author Tomaz Lavieri
 * @see ControlledLogic
 * @see DeniedLogic
 * @see LoginLogic
 */
@Stereotype
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ControlledResource {
	
	/**
	 * (Opcional)
	 * Nome único que identifica o recurso para o controle de acesso.<br/>
	 * <br/>Nomes duplicados gerarão erros de {@link RuntimeException}.<br/>
	 * <br/>Caso o nome do recurso não seja ajustado, ele será definido
	 * pelas regras na classe {@link AccessControlNameResolved}.
	 */
	String value() default "";
	
	/**
	 * (Opcional)
	 * Classe do {@link ControlledResource} que contém a lógica de @{@link DeniedLogic}
	 * para onde a lógica será redirecionada caso o usuário esteja logado e o acesso
	 * a lógica acessada seja {@link #locked()} e o usuário não tenha permissão para
	 * abrir a página.<br/>
	 * <br/><tt>result.redirectTo(recurso.class).deniedPageLogic();</tt><br/>
	 * <br/>Caso não seja setada a classe, a propria classe com esta anotação será usada</br>
	 * <br/>Caso a classe enviada não contenha uma lógica anotada com @{@link DeniedLogic}
	 *  o recurso sera redirecionada para sendError(403).
	 *  @see DeniedLogic
	 */
	Class<?> deniedLogic() default Void.class;
	
	/**
	 * (Opcional)
	 * Classe do {@link ControlledResource} que contém a lódigca de @{@link LoginLogic}
	 * para onde a lógica será redirecionada caso o usuário não esteja logado e o acesso
	 * a lógica em acessada seja {@link #locked()}.<br/>
	 * <br/><tt>result.redirectTo(recurso.class).loginPageLogic();</tt><br/>
	 * <br/>Caso não seja setada a classe, a propria classe com esta anotação será usada<br/>
	 * <br/>Caso a classe enviada não contenha uma lógica anotada com @{@link LoginLogic}
	 *  o recurso sera redirecionada para sendError(404).
	 */
	Class<?> loginLogic() default Void.class;
	
	/**
	 * (Opcional)
	 * Define se o acesso padrão das lógicas deste recurso controlado é fechado ou aberto.<br/>
	 * <br/>Por definição essa propriedade fecha as lógicas, só se fazendo necessário usar a
	 * propriedade quando há necessidade de por padrão deichar as lógicas abertas.<br/>
	 * <br/>O acesso de uma lógicas podem ser definida separadamente usando a propriedade locked
	 * da anotação @{@link ControlledLogic}.
	 * @see ControlledLogic
	 */
	boolean locked() default true;
	
	/**
	 * (Opcional)
	 * Define o objeto @{@link SessionScoped} que guarda as informações de login para 
	 * este @{@link ControlledResource}, ou seja, uma classe que implemente {@link LoginSession}<br/>
	 * <br/>Caso nenhuma classe for definida nesta propriedade, objeto único que implementa
	 * a interface {@link DefaultLoginSession} será solicitada por injeção.
	 * @see DefaultLoginSession
	 * @see LoginSession 
	 */
	Class<? extends LoginSession> sessionClass() default DefaultLoginSession.class;
	
	
}
